using System;
using System.Collections.Generic;
using System.Text;
using System.Security;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Security;
using System.Security.Permissions;
using System.IO;
using System.Collections.ObjectModel;
using System.Reflection;

namespace DP.Sharepoint.Workflow.Install
{
    [PermissionSet(SecurityAction.Demand)]
    public abstract class WebConfigModifier : SPFeatureReceiver
    {
        // Fields
        private List<SPWebConfigModification> mListModifications = new List<SPWebConfigModification>();

        // Methods
        protected WebConfigModifier()
        {
        }

        protected abstract void AddConfigurationToWebConfig(SPWebApplication app);

        protected void AddNodeValue(string name, string xpath, string scriptResource)
        {
            this.mListModifications.Add(this.GetSPWebModifChild(name, xpath, scriptResource));
        }

        protected void AddOrRemoveHandler(SPFeatureReceiverProperties properties, bool removeModification)
        {
            if (properties == null)
            {
                throw new ArgumentNullException("properties");
            }
            
            SPWebApplication app = properties.Feature.Parent as SPWebApplication;

            if (app == null)
            {
                SPSite site = properties.Feature.Parent as SPSite;

                if (site == null)
                {
                    SPWeb web = properties.Feature.Parent as SPWeb;
                    if (web != null)
                    {
                        app = web.Site.WebApplication;
                    }
                }
                else
                {
                    app = site.WebApplication;
                }
            }

            if (app == null)
            {
                throw new ArgumentOutOfRangeException(properties.Feature.Parent.ToString());

            }
            if (!removeModification)
            {
                this.AddConfigurationToWebConfig(app);
            }
            else
            {
                this.RemoveWebConfigEntries(app, this.OwnerModif);
            }
            app.Update();
        }

        protected void AddSection(string name, string xpath)
        {
            this.mListModifications.Add(this.GetSPWebModifSection(name, xpath));
        }

        protected void DoTrace(string Message)
        {
            TraceProvider.WriteTrace(0, TraceProvider.TraceSeverity.High, Guid.Empty, Assembly.GetExecutingAssembly().FullName, this.OwnerModif, this.OwnerModif + ".Config", Message);
        }

        [SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            bool removeModification = false;
            this.AddOrRemoveHandler(properties, removeModification);
        }

        [SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            bool removeModification = true;
            this.AddOrRemoveHandler(properties, removeModification);
        }

        [SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
        public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        {
        }

        [SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
        public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        {
        }

        protected SPWebConfigModification GetSPWebModifAttribut(string name, string xpath, string value)
        {
            SPWebConfigModification modification = new SPWebConfigModification(name, xpath);
            modification.Owner = this.OwnerModif;
            modification.Sequence = 0;
            modification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureAttribute;
            modification.Value = value;
            return modification;
        }

        protected SPWebConfigModification GetSPWebModifChild(string name, string xpath, string scriptResource)
        {
            SPWebConfigModification modification = new SPWebConfigModification(name, xpath);
            modification.Owner = this.OwnerModif;
            modification.Sequence = 0;
            modification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
            modification.Value = scriptResource;
            return modification;
        }

        protected SPWebConfigModification GetSPWebModifSection(string name, string xpath)
        {
            SPWebConfigModification modification = new SPWebConfigModification(name, xpath);
            modification.Owner = this.OwnerModif;
            modification.Sequence = 0;
            modification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureSection;
            return modification;
        }

        protected void RemoveWebConfigEntries(SPWebApplication oWebApp, string owner)
        {
            Collection<SPWebConfigModification> webConfigModifications = oWebApp.WebConfigModifications;
            int num = webConfigModifications.Count;
            for (int i = num - 1; i >= 0; i--)
            {
                SPWebConfigModification modification = webConfigModifications[i];
                if (modification.Owner == owner)
                {
                    webConfigModifications.Remove(modification);
                }
            }
            if (num > webConfigModifications.Count)
            {
                oWebApp.Update();
                SPFarm.Local.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
            }
        }

        protected void SaveWebConfig(SPWebApplication application)
        {

            foreach (SPWebConfigModification m in this.mListModifications)
            {

                application.WebConfigModifications.Add(m);
            }

            this.mListModifications.Clear();

            SPFarm.Local.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
        }

        // Properties
        protected abstract string OwnerModif { get; }
    }





}
